# 背景

Http 协议是无状态的。

任何的请求都是可以伪造的。

所以在 API 接口设计的时候 就需要判断调用方是否是我们信任的系统。

# 实现

一般前端具有 appId appSecret

前端加密步骤

  • 参数中添加 时间戳 yyyy-MM-dd HH:mm:ss
  • JSON Key 排序
  • sign = MD5(JSON.stringify(jsonStr + appSecret))
  • json.sign = sign.toUpperCase();
  • aes 加密

参考代码

  __encodeAesString(data, key) {
    key = CryptoJS.enc.Utf8.parse(key);
    data = CryptoJS.enc.Utf8.parse(data);
    const encrypted = CryptoJS.AES.encrypt(data, key, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7,
    });
    //  返回的是base64格式的密文
    return encrypted.toString();
  }

  __keySort(json) {
    const sortedKeys = Object.keys(json)
      .filter(f => ![null, undefined].some(s => s === json[f]))
      .sort();

    return sortedKeys.reduce((acc, key) => {
      if (json[key] && Array.isArray(json[key])) {
        acc[key] = json[key];
        return acc;
      }

      if (json[key] && typeof json[key] === 'object') {
        acc[key] = this.__keySort(json[key]);
      } else {
        acc[key] = json[key];
      }
      return acc;
    }, {});
  }

  __signStr(params) {
    params.timestamp = format(new Date(), 'yyyy-MM-dd HH:mm:ss');
    // sha1
    let signStr = JSON.stringify(this.__keySort(params));
    signStr = md5(
      signStr +
      this.appSecret
    );
    params.sign = signStr.toUpperCase();
    // aes
    const queryStr = this.__encodeAesString(
      JSON.stringify(this.__keySort(params)),
      this.appKey
    );
    return queryStr;
  }
最后编辑时间: 8/24/2020, 10:55:11 PM